package com.todo.event.activity.application.core.engine.aviator.common;

import com.google.common.collect.Lists;
import lombok.AllArgsConstructor;
import lombok.Getter;

import java.math.BigDecimal;
import java.util.Arrays;
import java.util.List;
import java.util.Objects;
import java.util.stream.Collectors;

/**
 * @author azhebuxing
 * @date 2025/1/9 09:07
 * @description
 */
@Getter
@AllArgsConstructor
public enum SignEnum {
    GT(">", "大于", "<=", SignTypeEnum.RELATION),
    GE(">=", "大于等于", "<", SignTypeEnum.RELATION),
    LT("<", "小于", ">=", SignTypeEnum.RELATION),
    LE("<=", "小于等于", ">", SignTypeEnum.RELATION),
    EQ("=", "等于", "=", SignTypeEnum.RELATION),
    DEQ("==", "等于", "==", SignTypeEnum.RELATION),
    AND("&", "与", "|", SignTypeEnum.LOGIC),
    DAND("&&", "短路与", "||", SignTypeEnum.LOGIC),
    OR("|", "或", "&", SignTypeEnum.LOGIC),
    DOR("||", "短路或", "&&", SignTypeEnum.LOGIC),
    PLUS("+", "加", "-", SignTypeEnum.OPERATOR),
    MINUS("-", "减", "+", SignTypeEnum.OPERATOR),
    MULTIPLY("*", "乘", "/", SignTypeEnum.OPERATOR),
    DIVIDE("/", "除", "*", SignTypeEnum.OPERATOR),
    LB("(", "左侧小括号", ")", SignTypeEnum.BRACKETS),
    RB(")", "右侧小括号", "(", SignTypeEnum.BRACKETS);

    private final String val;
    private final String name;
    private final String inverseSign;
    private final SignTypeEnum type;

    public static SignEnum match(String val) {
        return Arrays.stream(SignEnum.values())
                .filter(item -> Objects.equals(item.getVal(), val))
                .findFirst()
                .orElse(null);
    }

    public static List<SignEnum> noBracketsSigns() {
        return Arrays.stream(SignEnum.values())
                .filter(SignEnum::isNotBrackets)
                .collect(Collectors.toList());
    }

    public boolean isNotBrackets() {
        return type != SignTypeEnum.BRACKETS;
    }

    /**
     * 获取逆向符号
     */
    public SignEnum getInverseSign() {
        return match(inverseSign);
    }

    public List<SignEnum> getSubSigns() {
        switch (this) {
            case GE:
                return Arrays.asList(GE, GT, EQ);
            case LE:
                return Arrays.asList(LE, LT, EQ);
            default:
                return Lists.newArrayList(this);
        }
    }

    public List<String> getSubSignStr() {
        List<SignEnum> subSigns = getSubSigns();
        return subSigns.stream().map(SignEnum::getVal).collect(Collectors.toList());
    }

    public boolean compare(String v1, String v2) {
        Double t1 = Double.parseDouble(v1);
        Double t2 = Double.parseDouble(v2);
        return compare(t1, t2);
    }

    public boolean compare(Double v1, Double v2) {
        BigDecimal t1 = BigDecimal.valueOf(v1);
        BigDecimal t2 = BigDecimal.valueOf(v2);
        return compare(t1, t2);
    }

    public boolean compare(BigDecimal v1, BigDecimal v2) {
        int res = v1.compareTo(v2);
        switch (this) {
            case GT:
                return res > 0;
            case GE:
                return res >= 0;
            case LT:
                return res < 0;
            case LE:
                return res <= 0;
            case DEQ:
            case EQ:
                return res == 0;
            default:
                return false;
        }
    }

    public static SignEnum combineSign(SignEnum signA, SignEnum signB) {
        String combineSign = signA.getVal() + signB.getVal();
        return match(combineSign);
    }
}

